#include "p2p.h"

//The socket file descriptor for this application.
int socketfd;

//Debugging on/off
int debug = false;

/**
 * Peer-2-Peer networking application
 * ICS 451, Project 2
 *
 * Group members:
 *   - Emerson Tabucol
 *   - Kevin Leong
 *   - Leonardo Nyugen
 */

int main (int argc, char *argv[]) {
  
  //Stores port number of host machine
  short int port;
  
  //loop variables
  int i, j, k;
  
  //Initialize list of intial peers
  listInitialPeers.size = 0;
  listInitialPeers.maxSize = 20;
  
  //Initialize list of names of local content
  listLocalFiles.size = 0;
  listLocalFiles.maxSize = 20;
  
  //Initialize list of outstanding requests
  outstandingRequestsList.size = 0;
  outstandingRequestsList.maxSize = 3;
  
  //Initialize the content directory and data cache lists
  contentDirectoryList.size = 0;
  contentDirectoryList.maxSize = 16;
  
  dataCacheList.size = 0;
  dataCacheList.maxSize = 5;
	
	unsigned char buffer[MAX_MSG];

  /*******Handle command line arguments********/
  
  if (argc > 21) {
    error("Too many arguments entered.  Maximum allowed: 20");
  }
  else if (argc < 3) {
    error("Please enter a port number followed by at least 1 peer or filename");
  }
  else {
    //Check to see if valid port entered as first argument
    port = checkPort(argv[1]);
    
    //Check each argument for:
    //must only contain underscores, one period, lowercase letters
    //maximum length of a name is 20 bytes
    
    //loop through all command line arguments (except port number)
    //and separate them in lists of peers and host file names
    for (i = 2; i < argc; i++){
      parseArgument(&listLocalFiles, &listInitialPeers, argv[i]);
    }
  }
 
  /*******Configure Network Settings***********/
  
  //Designate protocol
  struct protoent * protocolEntry;
  if ((protocolEntry = getprotobyname("UDP")) == NULL){
    error("getprotobyname");
  }  
 
  //Socket file descriptor
  //int socketfd;
  
  //Sockaddr pointer to store address and port
  struct sockaddr * sap;
  
  //Sockaddr pointer to store sender's address and port
  struct sockaddr senderSap;
  
  //Create socket for sending and receiving
  if ((socketfd = socket(PF_INET, SOCK_DGRAM, protocolEntry->p_proto)) < 0){
    error("socket");
  }
  
  //Populate sockaddr pointer with address information from command line
  sap = configureHost(port);
  
  //Bind to the given socket and address
  if(bind(socketfd, sap, sizeof(*sap)) != 0) {
    error("bind");
  }
  
  /********P2P Functions**********************/

	// Sends out the initial listing message to all peers typed on the command-line.
	sendInitialListingMessage();
	
  //Ask for user input
  threadUserInput(); 
	threadListingMessage();
	checkRequests();
	
  //Enter infinite loop to read packets
  while(true){
    //Wait to receive a UDP packet.  Save sender port and address info
    //in senderSap sockaddr pointer
    int bytesReceived = receiveUDP(socketfd, buffer, sizeof(buffer), &senderSap);
    
    //Struct to store sender's address and port number
    struct addressPort senderInfo;
    
    //Enters information into struct that stores sender's address/port
    getAddressPort(&senderSap, &senderInfo);
    
    //DEBUG -  Print buffer contents
    if (debug) {
      printf("RECEIVED from PORT %d: ", senderInfo.port);
      printMessage(buffer, bytesReceived);
    }
		
    handleMessage(buffer, &outstandingRequestsList, senderInfo);
  } // End While Loop
  
}
